package com.easthome.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easthome.auth.mapper.SysUserMapper;
import com.easthome.auth.service.*;
import com.easthome.common.excelUtil.ExcelUtils;
import com.easthome.common.jwt.JwtHelper;
import com.easthome.common.result.Result;
import com.easthome.common.result.ResultCodeEnum;
import com.easthome.common.system.MenuHelper;
import com.easthome.model.system.*;
import com.easthome.security.custom.CustomUser;
import com.easthome.security.custom.LoginUserHelper;
import com.easthome.security.custom.Md5PasswordEncoder;
import com.easthome.vo.system.AssginRoleVo;
import com.easthome.vo.system.LoginVo;
import com.easthome.vo.system.RouterVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: 朱敦宇
 * @time: 2023/11/8 11:23
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SysLoginLogService loginLogService;

    @Override
    public Result toAssign(Long id) {
        //1.查询所有角色
        List<SysRole> roleList = sysRoleService.list();
        //2.查询该用户所属角色
        LambdaQueryWrapper<SysUserRole> sysUserRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserRoleLambdaQueryWrapper.eq(SysUserRole::getUserId,id);
        List<SysUserRole> userRoles = sysUserRoleService.list(sysUserRoleLambdaQueryWrapper);
        List<Long> allUserRoles = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("userRoleIds",allUserRoles);
        stringObjectHashMap.put("allRoles",roleList);
        return Result.ok(stringObjectHashMap);
    }
    @Transactional
    @Override
    public Result doAssign(AssginRoleVo assginRoleVo) {
        //1.删除原来所属角色
        LambdaUpdateWrapper<SysUserRole> sysUserRoleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        sysUserRoleLambdaUpdateWrapper.eq(SysUserRole::getUserId,assginRoleVo.getUserId());
        sysUserRoleService.remove(sysUserRoleLambdaUpdateWrapper);
        //2.将重置角色添加到表中
        if(assginRoleVo.getRoleIdList().size()>0){
            for (Long aLong : assginRoleVo.getRoleIdList()) {
                SysUserRole sysUserRole=new SysUserRole();
                sysUserRole.setUserId(assginRoleVo.getUserId());
                sysUserRole.setRoleId(aLong);
                sysUserRoleService.save(sysUserRole);
            }
        }

        return Result.ok();
    }

    @Override
    public List<SysRole> findRolesByUserId(Long userId) {
//        LambdaQueryWrapper<SysUserRole> sysUserRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
//        sysUserRoleLambdaQueryWrapper.eq(SysUserRole::getUserId,userId);
//        List<SysUserRole> list = sysUserRoleService.list(sysUserRoleLambdaQueryWrapper);
//        List<Long> roleIds = list.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());

        List<SysRole> roleList = baseMapper.selectRolesById(userId);
        return roleList;
    }

    @Override
    public List<String> findButtonsByUserId(Long userId) {
//        List<SysRole> roleList = baseMapper.selectRolesById(userId);
//        roleList.stream().filter()

        List<SysMenu> menusByUserId = baseMapper.findMenusByUserId(userId);
        List<String> collect = menusByUserId.stream().filter(menu -> menu.getType() == 2 && !StringUtils.isEmpty(menu.getPerms())).map(SysMenu::getPerms).collect(Collectors.toList());
        return collect;
    }

    /**
     * @description: 通过userId查找路由
     * @param userId

     */
    @Override
    public List<RouterVo> findRotersByUserId(Long userId) {
        if(userId == 1){
           return MenuHelper.toRouterTree(MenuHelper.toTreeMenu(sysMenuService.list()));
        }
       List<SysMenu>  menuList =  baseMapper.findMenusByUserId(userId);
       return MenuHelper.toRouterTree(MenuHelper.toTreeMenu(menuList));
    }
    /**
     * @description: 登陆业务，交由security框架处理
     * @param loginVo

     */
    @Override
    public Result login(LoginVo loginVo,HttpServletRequest request) {
        //生成登陆日志
        String ip = request.getRemoteAddr();
        String username = "";
        Integer loginFlag = 0;
//        loginLogService
        Date loginDate = new Date();

        //1.调用authenticationManager
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
        Authentication authentication = authenticationManager.authenticate(authenticationToken);
        CustomUser customUser = (CustomUser) authentication.getPrincipal();
        username = customUser.getUsername();
        SysLoginLog loginLog = new SysLoginLog();
        loginLog.setUsername(username);
        loginLog.setIpaddr(ip);
        loginLog.setAccessTime(loginDate);
        loginLog.setIsDeleted(0);
        loginLog.setCreateTime(loginDate);
        loginLog.setUpdateTime(loginDate);
        if (authentication == null){
            loginFlag = 1;
            loginLog.setStatus(loginFlag);
            loginLogService.save(loginLog);
            return Result.build(ResultCodeEnum.LOGIN_USER_ERROR);
        }
        loginLog.setMsg("登陆成功");
        loginLog.setStatus(loginFlag);
        loginLogService.save(loginLog);
        //2.没有问题放入context中
        SecurityContextHolder.getContext().setAuthentication(authentication);

        //3.获取认证成功后中包含的对象
//        CustomUser customUser = (CustomUser) authentication.getPrincipal();
        //4.将权限信息放入redis中
//        List<Authentication> authorities = authentication.getAuthorities();
        Collection<GrantedAuthority> authorities = customUser.getAuthorities();
        //stringRedisTemplate.boundValueOps("oa:login:id:"+customUser.getSysUser().getId()).set(JSON.toJSONString(authorities));
        //4.5存入redis中
        String permissionJson = JSON.toJSONString(authorities);
        stringRedisTemplate.opsForValue().set("oa:login:id:"+customUser.getSysUser().getId(),permissionJson);
        //5.生产token
        String token = JwtHelper.createToken(customUser.getSysUser().getId(), customUser.getSysUser().getUsername());
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        return Result.ok(map);
    }
    @Autowired
    private SysDeptService deptService;
    @Autowired
    private SysPostService postService;
    @Autowired
    private Md5PasswordEncoder md5PasswordEncoder;
    @Override
    public Map<String, Object> getCurrentUser() {
        Long userId = LoginUserHelper.getUserId().get();
        SysUser sysUser = baseMapper.selectById(userId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("name",sysUser.getName());
        map.put("phone",sysUser.getPhone());
        String deptName = deptService.getById(sysUser.getDeptId()).getName();
        map.put("deptName",deptName);
        String postName = postService.getById(sysUser.getPostId()).getName();
        if(StringUtils.isEmpty(postName)){
            postName = "随机部门";
        }
        map.put("postName",postName);
        return map;
    }

    @Override
    public String importUser(MultipartFile file) throws Exception {

        List<SysUser> users = ExcelUtils.readMultipartFile(file,SysUser.class);

        //进行密码转码

        users.forEach(item->{item.setStatus(1);item.setPhone(getPhone(item.getPhone()));item.setPassword(md5PasswordEncoder.encode(item.getPassword()));});
        boolean b = this.saveBatch(users);
//        System.out.println(users);
        return b+"";
    }
    public String getPhone(String str){
        String regEx="^([\\+|-]?\\d+(.{0}|.\\d+))[Ee]{1}([\\+|-]?\\d+)$";
        // 编译正则表达式
        Pattern pattern = Pattern.compile(regEx);
        // 忽略大小写的写法
        // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(str);
        // 字符串是否与正则表达式相匹配
        boolean rs = matcher.matches();
        // 判断是否为字符串的科学计数法
        if(rs){
            // 科学计数法转数字
            BigDecimal one = new BigDecimal(str);
            // 数字转字符串
            str = one.toPlainString();
        }
    return str;
    }

}
